// SINGULARITY HTML5 GAME ENGINE
// -----------------------------
// Copyright(c) 2013 by Codenova.pl

define(['./Core', './Animations/Animation'], function (Core, Animation) {
    var Mouse = function() {};
    var _Mouse = function() {};

    _Mouse.prototype = {
        ChangeUIElementState: function(el, e) {
            // Check cursor position for this elements
            if(Mouse.prototype.CursorOverElement(el, e)) {
                // Make sure user is doing it for the first time
                // otherwise we shouldn't make any actions
                if(!el.Hovered) {
                    // Yes, user is hovering current element for the
                    // first time so make him sure he's doing it :)

                    // What is more, cursor depends on element type,
                    // it differs for e.g. button and textbox
                    if(typeof el.InputType !== 'undefined') {
                        switch(el.InputType) {
                            case 'button':
                                Mouse.prototype.Cursor('pointer');
                                break;
                            case 'textbox':
                                Mouse.prototype.Cursor('text');
                                break;
                            default:
                                Mouse.prototype.Cursor('default');
                                break;
                        }
                    } else {
                        Mouse.prototype.Cursor('pointer');
                    }

                    _Mouse.prototype.PlayAudio(el.Id);
                    el.Hovered = true;

                    // Redraw UI for making a hovered element
                    _Mouse.prototype.RedrawUIForHover(el);
                }
            } else {
                // If we find hovered element, we should
                // reset its state
                if(el.Hovered) {
                    // Reset UI elements state
                    Mouse.prototype.Cursor('default');
                    el.Hovered = false;

                    // Redraw UI
                    _Mouse.prototype.RedrawUIForHover(el);
                }
            }
        },

        PlayAudio: function(elId) {
            "use strict";
            var audio = document.getElementById(elId);
            if(audio != null) {
                audio.load(); // Load audio for Chrome and fast hover in/out
                audio.play();
            }
        },

        RedrawUIForHover: function(obj) {
            // Clear UI stage
            Core.ClearCanvas(obj.Context, obj.Canvas.width, obj.Canvas.height);

            if(obj.Hovered) {
                // Hovered object, draw it with 'Hover' properties
                obj.Add(obj.Hover);
            } else {
                // Not-hovered object, draw it with basic properties
                obj.Add();

                // Set element's state to not-hovered
                obj.Hovered = false;
            }
        }
    };

    Mouse.prototype = {
        constructor: Mouse,

        AttachClickEvent: function(obj) {
            var _i, _length;
            var self = this;

            document.addEventListener('click', function(e) {
                for(_i = 0, _length = obj.Storage.Storage.length - 1; _i <= _length; _i = _i + 1) {
                    // Attach event for elements with attached events
                    if(obj.Storage.Storage[_i].Clickable) {
                        if(self.CursorOverElement(obj.Storage.Storage[_i], e)) {
                            switch(obj.Storage.Storage[_i].Click.Action) {
                                case 'alert':
                                    alert(obj.Storage.Storage[_i].Click.Data);
                                    break;
                                case 'stage':
                                    // Clear DOM
                                    var canvas = document.getElementsByTagName('canvas');
                                    var animation = Animation({
                                        Callback: obj.Storage.Storage[_i].Click.Data,
                                        Duration: 500,
                                        Element: canvas,
                                        RemoveElement: true,
                                        Type: 'fadeout'
                                    });
                                    animation.Trigger();

                                    // Back to standard cursor
                                    self.Cursor('default');

                                    // Initialize new stage
                                    obj.IsActive = false;
                                    break;
                                case 'close':
                                    // Close action expects that given
                                    // element has a prototype named 'Close'
                                    obj.Storage.Storage[_i].Click.Data.Close();
                                    break;
                                default:
                                    break;
                            }
                        }
                    }

                    // Attach event for specific UI elements
                    if(typeof obj.Storage.Storage[_i].InputType !== 'undefined') {
                        switch(obj.Storage.Storage[_i].InputType) {
                            case 'textbox':
                                if(self.CursorOverElement(obj.Storage.Storage[_i], e)) {
                                    // User clicked into textbox, attach set of extra
                                    // actions and properties, cursor etc.

                                    // Change element state
                                    obj.Storage.Storage[_i].Clicked = true;

                                    // We create HTML textbox for storing "real" data
                                    elId = 'textbox-for-' + obj.Storage.Storage[_i].Id;

                                    // Anchor to the created element
                                    elTextbox = document.getElementById(elId);

                                    // Create textbox only if there isn't any
                                    if(elTextbox == null) {
                                        Core.CreateHtmlElement('input', {
                                            type: 'textbox',
                                            id: elId,
                                            'data-focus': '0'
                                        });
                                        elTextbox = document.getElementById(elId);

                                        // Attach onChange event for HTML textbox
                                        obj.Storage.Storage[_i].AttachChangeEvent(elTextbox);
                                    }

                                    // Focus on created element
                                    elTextbox.focus();
                                    elTextbox.setAttribute('data-focus', '1');

                                    // Attach caret
                                    // We have to assign element to the variable
                                    // cause in the loop it is loosing its iterator
                                    var el = obj.Storage.Storage[_i];
                                    requestAnimationFrame(function() {
                                        Core.RedrawUIForClick(el);
                                        el.AttachCaret(el.Context, 0);
                                    });
                                } else {
                                    // If we have clicked element, reset caret
                                    // and its state
                                    if(obj.Storage.Storage[_i].Clicked) {
                                        // Reset element's clicked state cause
                                        // it is not our target
                                        obj.Storage.Storage[_i].Clicked = false;

                                        // Remove focus from connected textbox
                                        document.getElementById('body').focus();
                                        var elId = 'textbox-for-' + obj.Storage.Storage[_i].Id;
                                        var elTextbox = document.getElementById(elId);
                                        elTextbox.setAttribute('data-focus', '0');
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
            });
        },

        /**
         * Handles hover event for given storage
         * @param obj
         * @constructor
         * @param attachYN
         */
        AttachHoverEvent: function(obj) {
            var handler = function(e) {
                var _i, _length;

                if(obj.IsActive) {
                    for(_i = 0, _length = obj.Storage.Storage.length - 1; _i <= _length; _i = _i + 1) {
                        // Check if element is hoverable
                        if(obj.Storage.Storage[_i].Hoverable) {
                            _Mouse.prototype.ChangeUIElementState(obj.Storage.Storage[_i], e);
                        }
                    }
                }
            };

            document.addEventListener('mousemove', handler, false);
        },

        /**
         * Changes cursor appearance
         * @param cursor
         * @constructor
         */
        Cursor: function(cursor) {
            document.body.style.cursor = cursor;
        },

        /**
         * Returns if cursor is over chosen element
         * @param el
         * @param e
         * @returns {boolean}
         * @constructor
         */
        CursorOverElement: function(el, e) {
            return this.GetCoordinates(e).mouseX >= el.X &&
                this.GetCoordinates(e).mouseX <= el.X + el.Width &&
                this.GetCoordinates(e).mouseY >= el.Y &&
                this.GetCoordinates(e).mouseY <= el.Y + el.Height;
        },

        /**
         * Gets current cursor coordinates
         * @param event
         * @returns {{mouseX: number, mouseY: number}}
         * @constructor
         */
        GetCoordinates: function(event) {
            return {
                mouseX: event.clientX + document.body.scrollLeft,
                mouseY: event.clientY + document.body.scrollTop
            }
        }
    };

    return Mouse.prototype;
});